package com.music;

import com.data.MusicFile;
import com.effects.BasicEffect;
import com.gooddies.utils.FileUtils;
import com.gui.mainwindow.MainWindow;
import com.music.players.IPlayer;
import com.music.players.IPlayer.PlayerStatus;
import com.music.players.Mp3Player2;
import com.music.players.WavPlayer;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JOptionPane;
import javazoom.jlgui.basicplayer.BasicController;
import javazoom.jlgui.basicplayer.BasicPlayerEvent;
import javazoom.jlgui.basicplayer.BasicPlayerException;
import javazoom.jlgui.basicplayer.BasicPlayerListener;

/**
 * @author sad
 */
public class MusicManager {

    private static final MusicManager instance = new MusicManager();
    private MusicProvider mprovider;
    private final HashMap<String, IPlayer> musicToId = new HashMap<>();
    private MusicEvent progressEvent;
    private boolean initialized = false;
    private boolean errorShown = false;

    public static MusicManager getInstance() {
        return instance;
    }

    public void setProgressEvent(MusicEvent progressEvent) {
        this.progressEvent = progressEvent;
    }

    public void setMusicProvider(MusicProvider mProvider) {
        this.mprovider = mProvider;
    }

    private void stopAll() {
        if (!initialized) {
            return;
        }
        for (IPlayer player : musicToId.values()) {
            if (player.getStatus() == PlayerStatus.Play) {
                player.stop();
            }
        }
    }

    public void stopMusicPlayedById() {
        for (IPlayer player : musicToId.values()) {
            if (player.getStatus() == PlayerStatus.Play) {
                player.stop();
            }
        }
    }

    private String getMusicFolder() {
        return new File(".", "music").getAbsolutePath();
    }

    public void playEffect(String effectId) throws BasicPlayerException {
        if (!initialized) {
            return;
        }

        IPlayer player = musicToId.get(effectId);
        if (player == null) {
            System.out.println("Music with id " + effectId + " is not found");
            return;
        }
        player.play();
        /*try {
         if (player.getStatus() == BasicPlayer.PAUSED) {
         player.resume();
         } else if (player.getStatus() == BasicPlayer.STOPPED) {
         player.play();
         }
         if (player.getStatus() == BasicPlayer.PLAYING) {
         player.seek(0);
         player.play();
         }
         } catch (BasicPlayerException ex) {
         ex.printStackTrace();
         }*/
    }

    public void playById(String musicId, boolean showEffect) throws BasicPlayerException {
        if (!initialized) {
            return;
        }

        IPlayer player = musicToId.get(musicId);
        if (player == null) {
            System.out.println("Music with id " + musicId + " is not found");
            return;
        }

        if (showEffect) {
            BasicEffect effect = null;
            BasicEffect[] effects = BasicEffect.getAllEffects();
            for (MusicFile file : mprovider.getMusicFiles()) {
                if (file.getId().equals(musicId)) {
                    for (BasicEffect e : effects) {
                        if (e.getId().equals(file.getEffectId())) {
                            effect = e;
                            break;
                        }
                    }
                }
            }

            MainWindow.getInstance().setEffect(effect);
        } else {
            MainWindow.getInstance().setEffect(null);
        }
        player.play();
        /*if (player.getStatus() != BasicPlayer.PLAYING) {
         if (player.getStatus() == BasicPlayer.PAUSED) {
         try {
         player.resume();
         } catch (BasicPlayerException ex) {
         ex.printStackTrace();
         }
         } else {
         try {
         player.play();
         } catch (BasicPlayerException ex) {
         ex.printStackTrace();
         }
         }
         }*/
    }

    private BasicPlayerListener createPlayerListener() {
        return new BasicPlayerListener() {

            @Override
            public void opened(Object stream, Map properties) {

            }

            @Override
            public void progress(int bytesread, long microseconds, byte[] pcmdata, Map properties) {
                onProgress(pcmdata);
            }

            @Override
            public void stateUpdated(BasicPlayerEvent event) {

            }

            @Override
            public void setController(BasicController controller) {

            }
        };
    }

    private void onProgress(byte[] pcm) {
        if (progressEvent != null) {
            progressEvent.progress(pcm);
        }
    }

    private boolean muted = false;

    public boolean isMuted() {
        return muted;
    }

    public void mute() {
        muted = true;
        for (IPlayer player : musicToId.values()) {
            if (player.getStatus() == PlayerStatus.Play) {
                player.mute(true);
            }
        }
    }

    public void unmute() {
        muted = false;
        for (IPlayer player : musicToId.values()) {
            if (player.getStatus() == PlayerStatus.Play) {
                try {
                    player.mute(false);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    private File getFilePath(String path) {
        path = path.trim();
        if (path == null || path.isEmpty()) {
            return null;
        }

        File f = new File(path);
        if (f.exists()) {
            return f;
        }

        return new File(getMusicFolder(), path);
    }

    public void restart() {
        try {
            stopAll();
            for(IPlayer player:musicToId.values()){
                try{
                    player.close();
                }catch(Exception ex){}
            }
            //wheel2Player.clear();
            musicToId.clear();
            List<String> badFiles = new ArrayList<>();
            for (MusicFile file : mprovider.getMusicFiles()) {
                if (file.getFile() != null) {
                    File f = getFilePath(file.getFile());
                    try {
                        if (FileUtils.getFileExtension(new File(file.getFile())).equalsIgnoreCase("wav")) {
                            IPlayer player = new WavPlayer(f.getAbsolutePath());
                            musicToId.put(file.getId(), player);
                        } else {
                            Mp3Player2 player = new Mp3Player2(f.getAbsolutePath(), createPlayerListener());
                            musicToId.put(file.getId(), player);
                        }
                    } catch (Exception ex) {
                        badFiles.add("Cannot open music file as audio:'" + (f != null ? f.getAbsolutePath() : file.getFile()) + "'");
                    }
                }
            }

            if (!badFiles.isEmpty()) {
                JOptionPane.showMessageDialog(null, "Error in music files " + badFiles.toString().replace(',', '\n'));
            }
            initialized = true;
        } catch (IllegalArgumentException ex) {
            if (errorShown == false) {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(null, "Something wrong with your sound drivers:\n" + ex.getMessage());
                errorShown = true;
            }
            initialized = false;
        }
    }
}
